const {desktopCapturer, ipcRenderer} = require('electron');
const signalTypes = require('../../../signal_types');
const {log} = require('../../../utils/log');

const initPeerPuppet = async (controller_code) => {
  let pc;

  async function getScreenStream() {
    const sources = await desktopCapturer.getSources({types: ['window', 'screen']})
    log('sources:', sources);

    for (const source of sources) {
      //todo 可以让用户自己选 要分享整个窗口 还是某个window
      if (source.name === 'Entire Screen') {
        try {
          const stream = await navigator.mediaDevices.getUserMedia({
            audio: false,
            video: {
              mandatory: {
                chromeMediaSource: 'desktop',
                chromeMediaSourceId: source.id,

                // todo 若像线面这样设置 在远端是大屏(带鱼屏什么的)的情况下, 会出现 bug001 的情况
                // minWidth: 1280,
                // maxWidth: 1280,
                // minHeight: 720,
                // maxHeight: 720
              }
            }
          })

          return stream;
        } catch (e) {
          console.error(e)
        }
        return
      }
    }
  }

  // window.createAnswer = createAnswer
  async function createAnswer(offer) {
    const screenStream = await getScreenStream();
    log('screenStream:', screenStream);

    if (!screenStream) return;
    screenStream.getTracks().forEach(track => {
      log('addTrack ---> track:', track);
      pc.addTrack(track, screenStream);
    });

    await pc.setRemoteDescription(offer);
    await pc.setLocalDescription(await pc.createAnswer());

    log('createAnswer pc.localDescription', JSON.stringify(pc.localDescription));
    return pc.localDescription;
  }

  // window.addIceCandidate = addIceCandidate
  async function addIceCandidate(candidate,candidates) {
    if (!candidate) return

    candidates.push(candidate)
    //`addIceCandidate`必须在调用`setRemoteDescription`之后使用, 否则会报错: [12544:0813/220913.805:ERROR:sdp_offer_answer.cc(2280)] AddIceCandidate: ICE candidates can't be added without any remote session description.
    if (pc.remoteDescription && pc.remoteDescription.type) {
      for (let i = 0; i < candidates.length; i++) {
        await pc.addIceCandidate(new RTCIceCandidate(JSON.parse(candidates[i])))
      }
      candidate.length = 0;
    }
  }

  pc = new window.RTCPeerConnection({
    iceServers: [
      {
        urls: 'stun:stun.l.google.com:19302'
      }
    ]
  });
  window.pc = pc;

  //响应控制端发来的指令
  pc.ondatachannel = e => {
    log('pc.ondatachannel e:', e);
    log('pc.ondatachannel label:', e.channel.label);
    e.channel.onmessage = e => {
      // log('e.channel.onmessage:', e)
      const {type, data} = JSON.parse(e.data);

      if (type.startsWith('mouse')) {
        //被控制方当前的屏幕尺寸
        data.screen = {
          width: window.screen.width,
          height: window.screen.height
        }
        // log('data.screen:', data.screen);
        if(type!=='mousemove'){
          log('e.channel.onmessage--- --- ---【type】:',type);
          log('data:', data);
        }
      }
      ipcRenderer.send('robot', type, data);
    };
  };

  pc.onicecandidate = function (e) {
    log('pc.onicecandidate e', e)

    if (e.candidate) {
      ipcRenderer.send(signalTypes["SIGNAL_SERVER:CONTROL:FORWARD"], 'puppet-candidate', controller_code, JSON.stringify(e.candidate));
    }
  }

  const candidates = []
  const onCandidate = (e, candidate) => {
    log('addIceCandidate:', candidate);
    addIceCandidate(candidate,candidates);
  };
  ipcRenderer.on('candidate', onCandidate);

  const onOffer = async (e, offer) => {
    const answer = await createAnswer(offer);
    log('answer:', answer);
    ipcRenderer.send(signalTypes["SIGNAL_SERVER:CONTROL:FORWARD"], 'answer', controller_code, {type: answer.type, sdp: answer.sdp});
  };
  ipcRenderer.on('offer', onOffer);

  // 控制方主动断开连接
  ipcRenderer.once(signalTypes["CONTROL_WINDOW:CLOSE"], (e) => {
    log('--- --- --- clear peer-puppet --- --- ---')
    clear();
  });

  const clear = () => {
    ipcRenderer.off('candidate', onCandidate);
    ipcRenderer.off('offer', onOffer);
    log('--- --- --- pc.close --- --- ---')
    pc.close();
    pc = null;
  };
}

module.exports = {
  initPeerPuppet
}
